#pragma once

#include <string>
#include <vector>

#include "torrent/fwd_decl.hpp"

namespace bencode_helper {

typedef std::vector<std::string> StringList;
typedef std::vector<StringList> StringListList;

std::string get_str(be_node* dict, const std::string& key);
long long get_i64(be_node* dict, const std::string& key);
int get_int(be_node* dict, const std::string& key);
be_node* get_list(be_node* dict, const std::string& key);
be_node* get_dict(be_node* dict, const std::string& key);
char* get_cstr(be_node* dict, const std::string& key, long long& len);

StringList get_path(be_node* dict, const std::string& key = "path");
StringListList get_announce_list(be_node* dict, const std::string& key = "announce-list");
StringList get_str_list(be_node* dict, const std::string& key);

be_node* get_node_from_key(be_node* from, const std::string& key);
std::string get_bencoded_str_from_node(be_node* from);

torrent::MetaInfo get_meta_info(be_node* from);

struct be_node_ptr
{
	be_node_ptr(be_node* node) : _node(node) {}
	~be_node_ptr();
	be_node* _node;

	be_node& operator*() const // never throws
	{
		return *_node;
	}

	be_node* operator->() const // never throws
	{
		return _node;
	}

	be_node* get() const // never throws
	{
		return _node;
	}

	void reset(be_node* p = 0) // never throws
	{
		be_node_ptr(p).swap(*this);
	}

	void swap(be_node_ptr& b) // never throws
	{
		be_node* tmp = b._node;
		b._node = _node;
		_node = tmp;
	}
};

}
